home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / xvisrc.zip / ALLOC.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  6KB  |  296 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)alloc.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     alloc.c
  14. * module function:
  15.     Various routines dealing with allocation
  16.     and deallocation of data structures.
  17. * history:
  18.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  19.     Originally by Tim Thompson (twitch!tjt)
  20.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  21.     Heavily modified by Chris & John Downey
  22.  
  23. ***/
  24.  
  25. #include "xvi.h"
  26.  
  27. /*
  28.  * We use a special strategy for the allocation & freeing of Change
  29.  * structures to make these operations as fast as possible (since we
  30.  * have to allocate one for each input character in INSERT & REPLACE
  31.  * states).
  32.  *
  33.  * So we have a linked list of reusable Change structures; freeing a
  34.  * Change means just adding it to this list.
  35.  */
  36. static Change    *chlist = NULL;
  37.  
  38. /*
  39.  * Free a Change structure. This just means adding it to our list of
  40.  * reusable structures, so a later request for an allocation of a
  41.  * Change can be satisfied very quickly from the front of the list.
  42.  */
  43. void
  44. chfree(ch)
  45.     Change *ch;
  46. {
  47.     ch->c_next = chlist;
  48.     chlist = ch;
  49. }
  50.  
  51. Change *
  52. challoc()
  53. {
  54.     if (chlist) {
  55.     Change    *ch;
  56.  
  57.     ch = chlist;
  58.     chlist = chlist->c_next;
  59.     return ch;
  60.     }
  61.     return (Change *) alloc(sizeof (Change));
  62. }
  63.  
  64. /*
  65.  * We also use a similar strategy for Line structures.
  66.  */
  67. static Line    *lnlist = NULL;
  68.  
  69. char *
  70. alloc(size)
  71. unsigned size;
  72. {
  73.     char *p;        /* pointer to new storage space */
  74.  
  75.     while ((p = malloc(size)) == NULL) {
  76.     /*
  77.      * No more memory in the heap, but we may be able to
  78.      * satisfy the request by recycling entries in one of
  79.      * our lists of reusable structures.
  80.      */
  81.     if (lnlist) {
  82.         p = (char *) lnlist;
  83.         lnlist = lnlist->l_next;
  84.         free(p);
  85.     } else if (chlist) {
  86.         p = (char *) chlist;
  87.         chlist = chlist->c_next;
  88.         free(p);
  89.     } else {
  90.         /*
  91.          * No: we're out.
  92.          */
  93.         show_error(curwin, "Not enough memory!");
  94.         break;
  95.     }
  96.     }
  97.     return(p);
  98. }
  99.  
  100. char *
  101. strsave(string)
  102. const char *string;
  103. {
  104.     char    *space;
  105.  
  106.     space = alloc((unsigned) strlen(string) + 1);
  107.     if (space != NULL)
  108.     (void) strcpy(space, string);
  109.     return(space);
  110. }
  111.  
  112. /*
  113.  * Allocate and initialize a new line structure with room for
  114.  * 'nchars' characters.
  115.  */
  116. Line *
  117. newline(nchars)
  118. int    nchars;
  119. {
  120.     register Line    *l;
  121.     char        *ltp;
  122.  
  123.     if (lnlist == NULL) {
  124.     register unsigned n;
  125.  
  126.     /*
  127.      * To avoid memory fragmentation, we try to allocate a
  128.      * contiguous block of 100 Line structures if we
  129.      * haven't already got any.
  130.      *
  131.      * This means that, for every 100 lines of a file we
  132.      * read in, there should be a block of Line
  133.      * structures, which may never be freed, followed by
  134.      * a large arena for the lines' text and other sundry
  135.      * dynamically allocated objects, which generally will
  136.      * be.
  137.      *
  138.      * If we can't even get one structure, alloc() should
  139.      * print an error message. For subsequent ones, we use
  140.      * malloc() instead because it isn't necessarily a
  141.      * serious error if we can't get any more space than
  142.      * we've actually been asked for.
  143.      */
  144.     if ((lnlist = (Line *) alloc(sizeof(Line))) == NULL) {
  145.         return(NULL);
  146.     }
  147.     lnlist->l_next = NULL;
  148.     for (n = 99; n != 0; n--) {
  149.         if ((l = (Line *) malloc(sizeof(Line))) == NULL) {
  150.         break;
  151.         }
  152.         l->l_next = lnlist;
  153.         lnlist = l;
  154.     }
  155.     }
  156.  
  157.     /*
  158.      * Assertion: lnlist != NULL.
  159.      */
  160.     l = lnlist;
  161.     lnlist = l->l_next;
  162.  
  163.     /*
  164.      * It is okay for newline() to be called with a 0
  165.      * parameter - but we must never call malloc(0) as
  166.      * this will break on many systems.
  167.      */
  168.     if (nchars == 0)
  169.     nchars = 1;
  170.     ltp = alloc((unsigned) nchars);
  171.     if (ltp == NULL) {
  172.     free((char *) l);
  173.     return(NULL);
  174.     }
  175.     ltp[0] = '\0';
  176.     l->l_text = ltp;
  177.     l->l_size = nchars;
  178.     l->l_prev = NULL;
  179.     l->l_next = NULL;
  180.  
  181.     return(l);
  182. }
  183.  
  184. /*
  185.  * bufempty() - return TRUE if the buffer is empty
  186.  */
  187. bool_t
  188. bufempty(b)
  189. Buffer    *b;
  190. {
  191.     return(buf1line(b) && b->b_file->l_text[0] == '\0');
  192. }
  193.  
  194. /*
  195.  * buf1line() - return TRUE if there is only one line
  196.  */
  197. bool_t
  198. buf1line(b)
  199. Buffer    *b;
  200. {
  201.     return(b->b_file->l_next == b->b_lastline);
  202. }
  203.  
  204. /*
  205.  * endofline() - return TRUE if the given position is at end of line
  206.  *
  207.  * This routine will probably never be called with a position resting
  208.  * on the zero byte, but handle it correctly in case it happens.
  209.  */
  210. bool_t
  211. endofline(p)
  212. Posn    *p;
  213. {
  214.     register char    *endtext = p->p_line->l_text + p->p_index;
  215.  
  216.     return(*endtext == '\0' || *(endtext + 1) == '\0');
  217. }
  218.  
  219. /*
  220.  * grow_line(lp, n)
  221.  *    - increase the size of the space allocated for the line by n bytes.
  222.  *
  223.  * This routine returns TRUE immediately if the requested space is available.
  224.  * If not, it attempts to allocate the space and adjust the data structures
  225.  * accordingly, and returns TRUE if this worked.
  226.  * If everything fails it returns FALSE.
  227.  */
  228. bool_t
  229. grow_line(lp, n)
  230. Line    *lp;
  231. register int    n;
  232. {
  233.     register int    nsize;
  234.     register char    *s;        /* pointer to new space */
  235.  
  236.     nsize = strlen(lp->l_text) + 1 + n;    /* size required */
  237.  
  238.     if (nsize <= lp->l_size)
  239.     return(TRUE);
  240.  
  241.     /*
  242.      * Need to allocate more space for the string. Allow some extra
  243.      * space on the assumption that we may need it soon. This avoids
  244.      * excessive numbers of calls to malloc while entering new text.
  245.      */
  246.     s = alloc((unsigned) nsize + SLOP);
  247.     if (s == NULL) {
  248.     return(FALSE);
  249.     }
  250.  
  251.     lp->l_size = nsize + SLOP;
  252.     (void) strcpy(s, lp->l_text);
  253.     free(lp->l_text);
  254.     lp->l_text = s;
  255.  
  256.     return(TRUE);
  257. }
  258.  
  259. /*
  260.  * Free up space used by the given list of lines.
  261.  *
  262.  * Note that the Line structures themselves are just added to the list
  263.  * of reusable ones.
  264.  */
  265. void
  266. throw(lineptr)
  267. Line    *lineptr;
  268. {
  269.     if (lineptr != NULL) {
  270.     Line    *newlist;
  271.  
  272.     newlist = lineptr;
  273.     for (;;) {
  274.         Line    *nextline;
  275.  
  276.         if (lineptr->l_text != NULL)
  277.         free(lineptr->l_text);
  278.         if ((nextline = lineptr->l_next) == NULL) {
  279.         /*
  280.          * We've reached the end of this list;
  281.          * join it on to lnlist ...
  282.          */
  283.         lineptr->l_next = lnlist;
  284.         /*
  285.          * ... & point lnlist at the beginning
  286.          * of this list.
  287.          */
  288.         lnlist = newlist;
  289.         return;
  290.         } else {
  291.         lineptr = nextline;
  292.         }
  293.     }
  294.     }
  295. }
  296.